<template>
  <view class="x-choose">
    <picker :disabled="props.disabled" @change="onChange" :value="index" range-key="label" mode="selector" :range="list">
      <view class="x-row x-label">
        <text v-if="showValue">{{showValue}}</text>
        <text v-else>{{props.label}}</text>
        <uni-icons type="down"></uni-icons>
      </view>
    </picker>
  </view>
</template>
<script>
export default {
  options: {
    styleIsolation: 'shared'
  },
}
</script>
<script setup name="x-select">
import {
  GlobalConfig, Msg
} from 'core';
const {
  appConfig
} = GlobalConfig();
const dict = appConfig.selectStore && appConfig.selectStore()
import {
  Helper,
  Log
} from "@/core";
import XCell from '@/components/lib/cell';
import {
  ref,
  toRaw,
  watch
} from "vue";

const props = defineProps({
  label: String,

  modelValue: [String, Number],

  options: {
    type: [Array, String],
  },

  type: {
    type: String,
    default: "dict"
  },

  count: {
    type: Number,
    default: -1
  },
  labelField: {
    type: [Array, String],
    default: "label",
  },

  valueField: {
    type: [Array, String],
    default: "code",
  },

  cache: {
    type: Boolean,
    default: false
  },

  query: {
    type: Object,
    default: () => {
      return {}
    }
  }
})

const emit = defineEmits([
  'update:modelValue',
  'onChange',
  'onClick'
])

const curValue = ref("")
const showValue = ref("")
const index = ref(0)
const list = ref([])
const source = ref([])

const setValue = (value) => {
  value = !Helper.empty(value) ? value : "";
  clear();
  if (!Helper.emptyArray(list.value)) {
    let idx = list.value.findIndex(x => x.value == value);
    if(idx > -1) {
      showValue.value = list.value[idx].label;
      index.value = idx;
    }
  }
  curValue.value = value;
}

const clear = () => {
  showValue.value = "";
  curValue.value = "";
  index.value = 0;
}

const init = async (options) => {
  if (!options) {
    return;
  }
  let data = [];
  if (typeof options == 'string') {
    data = await loadByRemote(options, props.query, props.cache);
  } else {
    data = options;
  }

  if (Helper.emptyArray(data)) {
    // Log.error(options);
    data = [];
  }

  source.value = data;

  if (props.count > -1 && data.length > props.count) {
    data = data.slice(0, props.count);
  }

  list.value = optionFormat(data);

  if (props.count > -1 && source.value.length > props.count) {
    handleValue(curValue.value);
  }

  setValue(curValue.value)
}

const loadByRemote = async (options, query, cache) => {
  //todo 验证store是否存在
  if (Helper.empty(dict)) {
    Msg.error("未配置下拉框store，请先检查配置");
    return;
  }
  //todo 处理为字典表码情况
  if (props.type == 'dict') {
    if (!dict.get) {
      Msg.error("未在stores中实现获取字典表码的接口");
      return;
    }

    let data = await dict.get(options, query, cache);
    return data;
  }

  if (Helper.empty(dict[options])) {
    // Msg.error("未实现下拉框的" + options + "，请选实现");
    return;
  }

  let resp = [];
  if (typeof dict[options] == 'function') {
    resp = await dict[options](query, cache);
  } else {
    resp = await dict[options];
  }

  return resp;
}

const handleValue = (value) => {
  setTimeout(() => {
    let index = list.value.findIndex(item => item[props.valueField] == value);
    if (index > -1) {
      return;
    }

    let option = source.value.find(item => item[props.valueField] == value);
    if (!Helper.emptyJson(option)) {
      let res = convert(option);
      if (!Helper.empty(res)) {
        list.value.push(res);
      }

    }
  }, 100)
}

const optionFormat = (options) => {
  let res = [];
  if (Array.isArray(options)) {
    options.forEach(i => {
      let item = convert(i);
      if (!Helper.empty(item)) {
        res.push(item);
      }
    })
  }

  return res;
}

const convert = (i) => {
  let config = {
    mapperValue: "code",
    mapperLabel: "label",
    enableField: false,
    labelField: props.labelField,
    valueField: props.valueField
  };
  let enableField = config.enableField;
  let item = Object.assign({}, i);
  let label = "";
  if (!enableField || i[enableField[0]] == enableField[1]) {
    if (!Array.isArray(config.labelField)) {
      label = i[config.labelField];
    } else {
      let labels = [];
      config.labelField.forEach(l => {
        let text = i[l];
        if (!Helper.empty(text)) {
          labels.push(text);
        }
      })

      label = labels.join("--")
    }

    item[config.mapperLabel] = label;
    item[config.mapperValue] = i[config.valueField];
    return item;
  }

  return null;
}

const onChange = (e) => {
  let option = getOption(e.target.value);
  // console.log(option, option.label, 'option')
  showValue.value = option.label;
  curValue.value = option.value;
  emit("onChange", curValue.value, showValue.value, option)
}

const getOption = (index) => {
  if (!Helper.emptyArray(list.value) && list.value.length > index) {
    return list.value[index];
  }

  return {};
}

const onClick = () => {
  emit('onClick', toRaw(curValue));
}

watch(curValue, (value) => {
  if(Helper.empty(value)) {
    value = "";
  }
  emit('update:modelValue', value)
})

watch(() => props.modelValue, (value) => {
  if(Helper.empty(value)) {
    value = "";
  }
  setValue(value)
},{immediate: true})

// 不知道为什么加了immediate会报错。后置解决
watch(() => props.options, (value) => {
  if(Helper.empty(value)) {
    return;
  }
  init(value)
}, {immediate: true})
</script>

<style scoped lang="less">
.x-row {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.control {
  font-size: 28rpx;
  input {
    width: 100%;
    // padding-right: 0 !important;
  }
}
</style>
